
`include "common_header.verilog"

//  *************************************************************************
//  File : block_type_10l
//  *************************************************************************
//  This program is controlled by a written license agreement.
//  Unauthorized Reproduction or Use is Expressly Prohibited. 
//  Copyright (c) 2001-2010 Morethanip
//  MorethanIP GmbH, GERMANY
//  info@morethanip.com
//  *************************************************************************
//  Version: $Id: block_type_10l.v,v 1.1.1.1 2014/07/15 08:12:14 dk Exp $
//  Author : Serge Sciberras
//  Initial: 12/13/2001
//  *************************************************************************
// 
//  Description: 10G Base-R PCS RX: block_type of decode block 
//               Full combinatorial block.
//  *************************************************************************

module block_type_10l (
   data_in,
   sh_in,
   class_block,
   `ifdef MTIPPCS_EEE_ENA
   r_type_li,   
   `endif
   r_type_c,
   r_type_s,
   r_type_t,
   r_type_d);

input   [63:0] data_in;         //  data input
input   [1:0] sh_in;            //  Sync header
output  [3:0] class_block;      //  Class block
`ifdef MTIPPCS_EEE_ENA
output  r_type_li;              //  LI Block type received
`endif
output  r_type_c;               //  C Block type received
output  r_type_s;               //  S Block type received
output  r_type_t;               //  T Block type received
output  r_type_d;               //  D Block type received

wire    [3:0]   class_block; 
`ifdef MTIPPCS_EEE_ENA
reg             r_type_li; 
`endif
reg             r_type_c; 
reg             r_type_s; 
reg             r_type_t; 
reg             r_type_d;  

wire    [8:0]   class_type_v; 
reg     [3:0]   class_block_int; 
reg             sh_data_ok; //  Sync header data ok
reg             sh_ctrl_ok; //  Sync header control ok
reg     [7:0]   ctrl_c; 
reg     [7:0]   ctrl_c_e; 
reg             o_code_0; 
reg             o_code_4; 
`ifdef MTIPPCS_EEE_ENA
wire    [7:0]   data_in_lpi; 
`endif


// =============================================================
parameter c_1e = 4'b 0001; //  1E 
parameter c_2d = 4'b 0010; //  2D 
parameter c_33 = 4'b 0011; //  33 
parameter c_66 = 4'b 0100; //  66 
parameter c_55 = 4'b 0101; //  55 
parameter c_78 = 4'b 0110; //  78 
parameter c_4b = 4'b 0111; //  4B 
parameter c_87 = 4'b 1000; //  87 
parameter c_99 = 4'b 1001; //  99 
parameter c_aa = 4'b 1010; //  AA 
parameter c_b4 = 4'b 1011; //  B4 
parameter c_cc = 4'b 1100; //  CC 
parameter c_d2 = 4'b 1101; //  D2 
parameter c_e1 = 4'b 1110; //  E1 
parameter c_ff = 4'b 1111; //  FF 

// verify that code is one of the known control codes from Table 49-1
// ------------------------------------------------------------------
function C_CHECK;
input [6:0] c;        
begin
        // allow all codes including reserved

        if (c == 7'b 0000000  | 
                `ifdef MTIPPCS_EEE_ENA
            c == 7'b 0000110  | // 06
                `endif
                `ifdef ENA_CLAUSE49_RESERVED
            c == 7'b 0101101  | // 2d: 1c
            c == 7'b 0110011  | // 33: 3c
            c == 7'b 1001011  | // 4b: 7c
            c == 7'b 1010101  | // 55: bc
            c == 7'b 1100110  | // 66: dc
            c == 7'b 1111000  | // 78: f7
                `endif
            c == 7'b 0011110 )  // 1e
        begin
                C_CHECK = 1'b 1;
        end
        else
        begin
                C_CHECK = 1'b 0;
        end
end
endfunction




//  determine type of current block and order it 0..15 according to table
//  ---------------------------------------------------------------------

assign class_type_v = {sh_in[0], data_in[7:0]}; 

always @(class_type_v)

   begin : p_class_block_int_0
   case (class_type_v)
   9'b 100011110:
      begin
      class_block_int = 4'b 0001;	//  1E
      end
   9'b 100101101:
      begin
      class_block_int = 4'b 0010;	//  2D
      end
   9'b 100110011:
      begin
      class_block_int = 4'b 0011;	//  33
      end
   9'b 101100110:
      begin
      class_block_int = 4'b 0100;	//  66
      end
   9'b 101010101:
      begin
      class_block_int = 4'b 0101;	//  55
      end
   9'b 101111000:
      begin
      class_block_int = 4'b 0110;	//  78
      end
   9'b 101001011:
      begin
      class_block_int = 4'b 0111;	//  4B
      end
   9'b 110000111:
      begin
      class_block_int = 4'b 1000;	//  87
      end
   9'b 110011001:
      begin
      class_block_int = 4'b 1001;	//  99
      end
   9'b 110101010:
      begin
      class_block_int = 4'b 1010;	//  AA
      end
   9'b 110110100:
      begin
      class_block_int = 4'b 1011;	//  B4
      end
   9'b 111001100:
      begin
      class_block_int = 4'b 1100;	//  CC
      end
   9'b 111010010:
      begin
      class_block_int = 4'b 1101;	//  D2
      end
   9'b 111100001:
      begin
      class_block_int = 4'b 1110;	//  E1
      end
   9'b 111111111:
      begin
      class_block_int = 4'b 1111;	//  FF
      end
   default:
      begin
      class_block_int = 4'b 0000;	//  default: data or error
      end
   endcase
   end

//  Decode Control Blocks
//  ---------------------
always @(sh_in)
   begin : p_class_block_int_1
   if (sh_in[1] == 1'b 1 & sh_in[0] == 1'b 0)
      begin
      sh_data_ok = 1'b 1;	
      end
   else
      begin
      sh_data_ok = 1'b 0;	
      end
   if (sh_in[1] == 1'b 0 & sh_in[0] == 1'b 1)
      begin
      sh_ctrl_ok = 1'b 1;	
      end
   else
      begin
      sh_ctrl_ok = 1'b 0;	
      end
   end

// -----------------------------------------------------------------------------------
//  Control caracter C0 to C7
// -----------------------------------------------------------------------------------
always @(data_in)
   begin : p_ctrl_c
   ctrl_c[0] = C_CHECK(data_in[14:8]);	
   ctrl_c[1] = C_CHECK(data_in[21:15]);	
   ctrl_c[2] = C_CHECK(data_in[28:22]);	
   ctrl_c[3] = C_CHECK(data_in[35:29]);	
   ctrl_c[4] = C_CHECK(data_in[42:36]);	
   ctrl_c[5] = C_CHECK(data_in[49:43]);	
   ctrl_c[6] = C_CHECK(data_in[56:50]);	
   ctrl_c[7] = C_CHECK(data_in[63:57]);
   
   if (data_in[14:8] == 7'b 0011110)
      begin
      ctrl_c_e[0] = 1'b 1;	
      end
   else
      begin
      ctrl_c_e[0] = 1'b 0;	
      end
// 
   if (data_in[21:15] == 7'b 0011110)
      begin
      ctrl_c_e[1] = 1'b 1;	
      end
   else
      begin
      ctrl_c_e[1] = 1'b 0;	
      end
// 
   if (data_in[28:22] == 7'b 0011110)
      begin
      ctrl_c_e[2] = 1'b 1;	
      end
   else
      begin
      ctrl_c_e[2] = 1'b 0;	
      end
// 
   if (data_in[35:29] == 7'b 0011110)
      begin
      ctrl_c_e[3] = 1'b 1;	
      end
   else
      begin
      ctrl_c_e[3] = 1'b 0;	
      end
// 
   if (data_in[42:36] == 7'b 0011110)
      begin
      ctrl_c_e[4] = 1'b 1;	
      end
   else
      begin
      ctrl_c_e[4] = 1'b 0;	
      end
// 
   if (data_in[49:43] == 7'b 0011110)
      begin
      ctrl_c_e[5] = 1'b 1;	
      end
   else
      begin
      ctrl_c_e[5] = 1'b 0;	
      end
// 
   if (data_in[56:50] == 7'b 0011110)
      begin
      ctrl_c_e[6] = 1'b 1;	
      end
   else
      begin
      ctrl_c_e[6] = 1'b 0;	
      end
// 
   if (data_in[63:57] == 7'b 0011110)
      begin
      ctrl_c_e[7] = 1'b 1;	
      end
   else
      begin
      ctrl_c_e[7] = 1'b 0;	
      end

// -------------------------------
//  O code 0
// ------------------------------
   if (data_in[35:32] == 4'b 0000 | data_in[35:32] == 4'b 1111)
      begin
//  Sequence 0x5c
      o_code_0 = 1'b 1;	
      end
   else
      begin
      o_code_0 = 1'b 0;	
      end
// 
// ------------------------------- 
//  O code 4
// ------------------------------
   if (data_in[39:36] == 4'b 0000 | data_in[39:36] == 4'b 1111)
      begin
      o_code_4 = 1'b 1;	
      end
   else
      begin
      o_code_4 = 1'b 0;	
      end
end



// -------------------------
//   LPI Block
// -------------------------   
`ifdef MTIPPCS_EEE_ENA

        assign data_in_lpi = {  (data_in[63:57] == 7'h 06), 
                                (data_in[56:50] == 7'h 06), 
                                (data_in[49:43] == 7'h 06), 
                                (data_in[42:36] == 7'h 06), 
                                (data_in[35:29] == 7'h 06), 
                                (data_in[28:22] == 7'h 06), 
                                (data_in[21:15] == 7'h 06), 
                                (data_in[14: 8] == 7'h 06) };

`endif            

// =====================================================================
//  level 2: qualify blocks for state machine
// =====================================================================
// -------------------------
//   C Block type received
// -------------------------   
always @(sh_ctrl_ok or class_block_int or ctrl_c or ctrl_c_e or o_code_0 or o_code_4
        `ifdef MTIPPCS_EEE_ENA
        or data_in_lpi
        `endif
        )
   begin : p_r_type_c
   if ( sh_ctrl_ok == 1'b 1 & class_block_int == c_1e & ctrl_c[7:0] == 8'b 11111111 & ctrl_c_e[7:0] == 8'b 00000000 | 
	sh_ctrl_ok == 1'b 1 & class_block_int == c_2d & ctrl_c[3:0] == 4'b 1111 & o_code_4 == 1'b 1 | 
	sh_ctrl_ok == 1'b 1 & class_block_int == c_4b & ctrl_c[7:4] == 4'b 1111 & o_code_0 == 1'b 1 | 
	sh_ctrl_ok == 1'b 1 & class_block_int == c_55 & o_code_0 == 1'b 1 & o_code_4 == 1'b 1)
      begin
        `ifdef MTIPPCS_EEE_ENA 
                if (sh_ctrl_ok == 1'b 1 & class_block_int == c_1e & ((|data_in_lpi)==1'b 1)) // any LPI?
                begin
                        if( data_in_lpi[7:0] == 8'h FF )
                        begin
                                // 8 lanes of LPI, OK
                                r_type_c  = 1'b 0;   
                                r_type_li = 1'b 1;
                        end
                        else if( data_in_lpi[7:0] == 8'h f0 | data_in_lpi[7:0] == 8'h 0f )
                        begin
                                // 4 lanes of LPI, OK, but not an LPI indication
                                r_type_c  = 1'b 1;   
                                r_type_li = 1'b 0;
                        end
                        else
                        begin
                                // not 4 or 8 columns of LPI, ERROR
                                r_type_c  = 1'b 0;   
                                r_type_li = 1'b 0;
                        end
                end
                else 
                begin
                        r_type_c  = 1'b 1;   
                        r_type_li = 1'b 0;
                end
        `else
        r_type_c = 1'b 1;	
        `endif
      end
   else
      begin
        r_type_c = 1'b 0;	
        `ifdef MTIPPCS_EEE_ENA            
        r_type_li = 1'b 0;
        `endif             	
      end
   end

// -------------------------
//   S Block type received
// -------------------------   
always @(sh_ctrl_ok or class_block_int or ctrl_c or o_code_0)
   begin : p_r_type_s
   if ( sh_ctrl_ok == 1'b 1 & class_block_int == c_33 & ctrl_c[3:0] == 4'b 1111 | 
        sh_ctrl_ok == 1'b 1 & class_block_int == c_66 & o_code_0 == 1'b 1 | 
	sh_ctrl_ok == 1'b 1 & class_block_int == c_78)
      begin
        r_type_s = 1'b 1;	
      end
   else
      begin
        r_type_s = 1'b 0;	
      end
   end

// -------------------------
//   T Block type received
// -------------------------   
always @(sh_ctrl_ok or class_block_int or ctrl_c)
   begin : p_r_type_t
   if ( sh_ctrl_ok == 1'b 1 & class_block_int == c_87 & ctrl_c[7:1] == 7'b 1111111 | 
        sh_ctrl_ok == 1'b 1 & class_block_int == c_99 & ctrl_c[7:2] == 6'b 111111 | 
	sh_ctrl_ok == 1'b 1 & class_block_int == c_aa & ctrl_c[7:3] == 5'b 11111 | 
	sh_ctrl_ok == 1'b 1 & class_block_int == c_b4 & ctrl_c[7:4] == 4'b 1111 | 
	sh_ctrl_ok == 1'b 1 & class_block_int == c_cc & ctrl_c[7:5] == 3'b 111 | 
	sh_ctrl_ok == 1'b 1 & class_block_int == c_d2 & ctrl_c[7:6] == 2'b 11 | 
	sh_ctrl_ok == 1'b 1 & class_block_int == c_e1 & ctrl_c[7] == 1'b 1 | 
	sh_ctrl_ok == 1'b 1 & class_block_int == c_ff)
      begin
        r_type_t = 1'b 1;	
      end
   else
      begin
        r_type_t = 1'b 0;	
      end
   end

// -------------------------
//   D Block type received
// -------------------------   
always @(sh_data_ok)
   begin : p_r_type_d
      r_type_d = sh_data_ok;	
   end


assign class_block = class_block_int;

endmodule // module block_type_10l
